package TS::SDT;

use strict;
use Scalar::Util qw(weaken);

use constant TABLE_MYSTREAM => 0x42;

sub new {
	my($pkg, $buffer) = @_;

	my $hash = {
		buffer => $buffer,

		table_id => undef,
		section_syntax_indicator => undef,
		private_indicator => undef,
		section_length => undef,
		transport_stream_id => 0,
		version_number => 0,
		current_next_indicator => 0,
		section_number => 0,
		last_section_number => 0,
		original_network_id => undef,
		reserved_future_use => undef,
		service => [],
		CRC_32 => undef,
	};

	my $s = bless $hash, $pkg;

	weaken($s->{buffer});
	$s->parse();

	return $s;
}

sub parse {
	my($s) = @_;

	$s->{table_id} = $s->{buffer}->getInt();

	if ($s->{table_id} == TABLE_MYSTREAM) {
		$s->mystream();
	} else {
		printf "#### no support table_id: 0x%02x\n", $s->{table_id};
#		exit;
	}
}

sub mystream {
	my($s) = @_;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$s->{section_syntax_indicator}	= $a >> 7 & 0x01;
	$s->{private_indicator}			= $a >> 6 & 0x01;
	$s->{section_length}			= ($a & 0x0F) << 8 | $b;
	my $program_endbyte = $s->{buffer}->{pos} + $s->{section_length};

	if ($s->{section_syntax_indicator}) {
		$s->{transport_stream_id} = $s->{buffer}->getShort();

		my $a = $s->{buffer}->getInt();
		$s->{version_number} = $a >> 1 & 0x1F;
		$s->{current_next_indicator} = $a & 0x01;

		$s->{section_number} = $s->{buffer}->getInt();
		$s->{last_section_number} = $s->{buffer}->getInt();
	}

	$s->{original_network_id} = $s->{buffer}->getShort();
	$s->{reserved_future_use} = $s->{buffer}->getInt();

	while ($s->{buffer}->{pos} + 4 < $program_endbyte - 4) {
		push(@{$s->{service}}, $s->service());
	}

	$s->{CRC_32} = $s->{buffer}->getLong();

	$s->{buffer}->{pos} = $program_endbyte;
}

sub service {
	my($s) = @_;

	my $ret = {};

	$ret->{service_id} = $s->{buffer}->getShort();

	my $a = $s->{buffer}->getInt();
	$ret->{reserved_future_use}			= $a >> 5 & 0x07;
	$ret->{EIT_user_defined_flags}		= $a >> 2 & 0x07;
	$ret->{EIT_schedule_flag}			= $a >> 1 & 0x01;
	$ret->{EIT_present_following_flag}	= $a      & 0x01;

	my $a = $s->{buffer}->getInt();
	my $b = $s->{buffer}->getInt();
	$ret->{running_status}	= $a >> 5 & 0x07;
	$ret->{free_CA_mode}	= $a >> 4 & 0x01;
	$ret->{descriptors_loop_length} = ($a & 0x0F) << 8 | $b;
	my $descriptor_loop_endbyte = $s->{buffer}->{pos} + $ret->{descriptors_loop_length};

	$ret->{descriptor} = [];

	while ($s->{buffer}->{pos} < $descriptor_loop_endbyte) {
		push(@{$ret->{descriptor}}, TS::Descriptor::parse($s->{buffer}));
	}

	$s->{buffer}->{pos} = $descriptor_loop_endbyte;

	return $ret;
}

1;
